package grpc

import (
	"calculate_server/internal/models/cutpart_queue"
	"context"
	"encoding/base64"
	"encoding/json"
	"fmt"
	common "jihe.common"
	"jihe.common/protos/calculate_server/proto"
	"jihe.common/protos/dispatch_server"
	dispatch_server_proto "jihe.common/protos/dispatch_server/proto"
	"jihe.common/tool"
	"strconv"
)

func (s *Server) CalculateCreateCutpartQueue(c context.Context, in *proto.CalculateCutpartQueues) (out *proto.CalculateNull, err error) {
	out = new(proto.CalculateNull)
	db := s.Pgsql.Get()
	tx, err := db.Begin()
	if err != nil {
		return
	}
	cutpartQueueTbl := cutpart_queue.NewTx(tx)
	err = cutpartQueueTbl.BatchCreate(in)
	if err != nil {
		_ = tx.Rollback()
		return
	}
	err = tx.Commit()
	return
}

func (s *Server) CalculateFashion(c context.Context, in *proto.CalculateFashionReq) (out *proto.CalculateFashionRes, err error) {
	out = new(proto.CalculateFashionRes)
	out.Errmsg = make(map[string]string)
	scriptParamMap := make(map[string]string)
	scriptParamMap["objUrl"] = in.ObjUrl
	scriptParamMap["type"] = in.Type
	scriptParamMap["kuoxing"] = in.Kuoxing
	scriptParamMap = tool.MergeMap(in.BodyData, scriptParamMap)
	bzData, e := s.AlgorithmService.BaseGetAlgorithmConfig(in.Tag)
	if e != nil {
		out.Errmsg["msg"] = "BaseGetAlgorithmConfig错误" + e.Error()
		return
	}
	scriptParamMap = tool.MergeMap(bzData, scriptParamMap)
	if len(in.AlgorithmParam) != 0 { //如果有选腋下点，就覆盖掉标准配置的
		yxyFloat, _ := strconv.ParseFloat(in.AlgorithmParam["YXY"], 64)
		bzXgFloat, _ := strconv.ParseFloat(bzData["M_Xiong_gao"], 64)
		if yxyFloat >= bzXgFloat {
			in.AlgorithmParam["YXY"] = fmt.Sprintf("%.6f", bzXgFloat-float64(1))
		}
		scriptParamMap = tool.MergeMap(in.AlgorithmParam, scriptParamMap)
	}
	paramB, e := json.Marshal(scriptParamMap)
	if e != nil {
		out.Errmsg["msg"] = "Marshal算法参数错误"
		return
	}
	out.Base64 = base64.StdEncoding.EncodeToString(paramB)

	areq := dispatch_server_proto.DispatchCmd{}
	areq.Timeout = 50000
	areq.Command = common.Configer.Algorithm.FashionCmd
	areq.Args = common.Configer.Algorithm.FashionArgs
	areq.Args = append(areq.Args, out.Base64)

	ret, err := dispatch_server.DoCmd(areq)
	if err != nil {
		return
	}
	if ret.Data["status"] != "ok" {
		err = fmt.Errorf(ret.Data["msg"])
		return
	}
	out.Url = ret.Data["url"]
	return
}

func (s *Server) CalculateGetCutpartQueueByNeedId(c context.Context, in *proto.CalculateCutpartQueue) (ret *proto.CalculateCutpartQueues, err error) {
	ret = new(proto.CalculateCutpartQueues)
	cutpartQueueTbl := cutpart_queue.NewModel(s.Pgsql.Get())
	ret.List, err = cutpartQueueTbl.GetByNeedId(in.NeedId)
	return
}

func (s *Server) CalculateGetNextCutpartByWait(c context.Context, in *proto.CalculateNull) (ret *proto.CalculateCutpartQueue, err error) {
	cutpartQueueTbl := cutpart_queue.NewModel(s.Pgsql.Get())
	return cutpartQueueTbl.GetNextWait()
}

func (s *Server) CalculateUpdateCompleteById(c context.Context, in *proto.CalculateCutpartQueue) (ret *proto.CalculateNull, err error) {
	ret = new(proto.CalculateNull)
	cutpartQueueTbl := cutpart_queue.NewModel(s.Pgsql.Get())
	err = cutpartQueueTbl.UpdateStatusById(in.Id, 5)
	return
}

func (s *Server) CalculateBegin(c context.Context, in *proto.CalculateCutpartQueue) (ret *proto.CalculateNull, err error) {
	ret = new(proto.CalculateNull)
	cutpartQueueTbl := cutpart_queue.NewModel(s.Pgsql.Get())
	err = cutpartQueueTbl.UpdateStatusById(in.Id, 2)
	return
}

func (s *Server) CalculateDeleteByNeedId(c context.Context, in *proto.CalculateCutpartQueue) (ret *proto.CalculateNull, err error) {
	ret = new(proto.CalculateNull)
	cutpartQueueTbl := cutpart_queue.NewModel(s.Pgsql.Get())
	err = cutpartQueueTbl.DeleteByNeedId(in.NeedId)
	return
}

func (s *Server) CalculateLineupNumByMinId(ctx context.Context, in *proto.CalculateLineupNumByMinIdReq) (out *proto.CalculateLineupNumByMinIdRes, err error) {
	out = new(proto.CalculateLineupNumByMinIdRes)
	out.Num = cutpart_queue.NewModel(s.Pgsql.Get()).GetCountByMiniId(in.MiniId)
	return
}

func (s *Server) CalculateAbort(ctx context.Context, in *proto.CalculateCutpartQueue) (out *proto.CalculateNull, err error) {
	out = new(proto.CalculateNull)
	err = cutpart_queue.NewModel(s.Pgsql.Get()).UpdateStatusByNeedId(in.NeedId)
	return
}

func (s *Server) GetBorderNode(ctx context.Context, in *proto.GetBorderNodeReq) (out *proto.GetBorderNodeRes, err error) {
	out = new(proto.GetBorderNodeRes)
	stdout, resultErr, isKilled := tool.RunCommandWithTimeout(5000, "python3", fmt.Sprintf("%s/broder_node.py", common.Configer.ScriptPath), in.ObjUrl)
	if isKilled {
		common.Loger.Error("%s,%s", stdout, resultErr)
		return
	}
	out.Stdout = stdout
	return
}

func (s *Server) GetDxfInfo(ctx context.Context, in *proto.GetDxfInfoReq) (out *proto.GetDxfInfoRes, err error) {
	out = new(proto.GetDxfInfoRes)
	stdout, resultErr, isKilled := tool.RunCommandWithTimeout(5000, "python3", fmt.Sprintf("%s/dxfFileData.py", common.Configer.ScriptPath), in.Base64)
	if isKilled {
		err = fmt.Errorf("%s,%s", stdout, resultErr)
		return
	}
	if resultErr != "" {
		err = fmt.Errorf("%s,%s", stdout, resultErr)
		return
	}
	out.Stdout = stdout
	return
}

func (s *Server) CalibrationUv(ctx context.Context, in *proto.CalibrationUvReq) (out *proto.CalibrationUvRes, err error) {
	out = new(proto.CalibrationUvRes)
	stdout, resultErr, isKilled := tool.RunCommandWithTimeout(5000, "python3", fmt.Sprintf("%s/unfold_uv.py", common.Configer.ScriptPath), in.Url)
	if isKilled {
		err = fmt.Errorf("%s,%s", stdout, resultErr)
		return
	}
	if resultErr != "" {
		err = fmt.Errorf("%s,%s", stdout, resultErr)
		return
	}
	out.Stdout = stdout
	return
}

func (s *Server) CalculateUpdateFail(c context.Context, in *proto.CalculateCutpartQueue) (ret *proto.CalculateNull, err error) {
	ret = new(proto.CalculateNull)
	db := s.Pgsql.Get()
	tx, err := db.Begin()
	if err != nil {
		return
	}
	cutpartQueueTbl := cutpart_queue.NewTx(tx)
	//先把当前ID更新未失败状态
	err = cutpartQueueTbl.UpdateStatusById(in.Id, 4)
	if err != nil {
		_ = tx.Rollback()
		return
	}
	//更新其他裁片为取消状态
	err = cutpartQueueTbl.UpdateCancelNeedId(in.NeedId)
	if err != nil {
		_ = tx.Rollback()
		return
	}
	err = tx.Commit()
	return
}
